/********************************************************************************
 ***                                                                          *** 
 ********************************************************************************
 *                                                                              * 
 *           Prject Name : MEMORIA                                              * 
 *                                                                              * 
 *             File Name : cardlist.cpp                                         * 
 *                                                                              * 
 *            Programmer : LBW                                                  * 
 *                                                                              * 
 *            Start Date : 2020/12/26                                           * 
 *                                                                              * 
 *           Last Update : 2020/12/26  [LBW]                                    * 
 *                                                                              * 
 *------------------------------------------------------------------------------*
 * Functions:                                                                   * 
 *   CardList::CardList -- 构造卡片集对象                                       * 
 *   CardList::fillVector -- 在数据库中检索卡片集的数据并储存到QVector容器中    *
 *   CardList::showCards -- 显示卡片                                            *
 *   CardList::hideCards -- 清除当前显示的卡片                                  *
 *   CardList::testButton_clicked -- 测试模式运行                               *
 *   CardList::editButton_clicked -- 编辑模式运行                               *
 *   CardList::sliderValueChanged -- 翻页                                       *
 *   CardList::insertButton_clicked -- 插入一张新的卡片                         *
 *   CardList::deleteButton_clicked -- 删除一张旧卡                             *
 *   CardList::saveButton_clicked -- 保存卡片集                                 *
 *   CardList::sqlMaker -- 转化成SQLite可以处理的语句                           *
 *   CardList::cardPressed -- 点击EditableCard对象触发的事件                    *
 *   CardList::getCardSum -- 返回卡片的总数                                     *
 *==============================================================================*/

#include <QtWidgets>
#include <QVector>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QMessageBox>

#include "parameter.h"
#include "cardlist.h"
#include "card.h"
#include "editableCard.h"

/**********************************************************************************
 * CardList::CardList -- 构造卡片集对象                                           *
 *                                                                                *
 *   卡片集包含测试用卡片和编辑用卡片，运行模式不同显示的卡片也不同               *
 *   EditableCard[]存在于CardList对象的整个周期中                                 *
 *   而Card[]只在test模式下实例化，退出test模式就直接被销毁                       *
 *                                                                                *
 * INPUT: dbName -- 卡片集的名字,用于搜索同名数据库                               *
 *        parent -- 指定CardList类的父对象                                        *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
CardList::CardList(const QString &dbName,QWidget *parent):QWidget(parent)
{
	dbNameRemain = dbName;
	QSqlDatabase db;
	if(QSqlDatabase::contains("qt_sql_default_connection"))	
		db = QSqlDatabase::database("qt_sql_default_connection");
	else
 		db = QSqlDatabase::addDatabase("QSQLITE");
	db.setDatabaseName("../user/" + dbName + ".db");
	
	if(!db.open())
		qDebug() << db.lastError().text();

	qDebug() << db.connectionName();

	QSqlQuery query;	

	//如果是新建的数据库要创建新的数据表
	query.exec(QString("create table cardlist(id int,heading text,sentence text,answer text,wordPos text,interference text);"));

	//查询card的数量
	query.exec("select count(*) from cardlist");
	query.next();
	cardSum = query.value(0).toInt();
	qDebug() << "cardSum is " << cardSum;
	//判断数据库是否为空
	
	//如果数据库有内容则创建容纳这些内容的容器
	heading.resize(cardSum);
	sentence.resize(cardSum);
	answer.resize(cardSum);
	wordPos.resize(cardSum);
	interference.resize(cardSum);
	
	//查询数据库，填充容器
	fillVector();
	
	//初始化界面
	cardListLayout = new QVBoxLayout;
	cardListLayout->setAlignment(Qt::AlignTop);
	setLayout(cardListLayout);
}

/**********************************************************************************
 * CardList::fillVector -- 在数据库中检索卡片集的数据并储存到QVector容器中        *
 *                                                                                *
 *   从数据库取出sentence,answer等数据后直接构造对应的EditableCard                *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void CardList::fillVector(){
	int i=0;
	QSqlQuery query;
	query.exec("select * from cardlist");
	while(query.next()){
		heading[i] = query.value("heading").toString();
		sentence[i] = query.value("sentence").toString();
		answer[i] = query.value("answer").toString();
		wordPos[i] = query.value("wordPos").toString();
		interference[i] = query.value("interference").toString();
		editableCards[i] = new EditableCard(i,heading[i],sentence[i],answer[i],wordPos[i],interference[i],this);
		connect(editableCards[i],SIGNAL(cardPressed(int)),this,SLOT(cardPressed(int)));
		i++;
	}
}

/**********************************************************************************
 * CardList::showCards -- 显示卡片                                                *
 *                                                                                *
 *   根据runMode的值来选择显示测试用卡片还是编辑用卡片                            *
 *   变量thisPageBegin决定是从第几张卡片开始显示                                  *
 *   变量cardsThisPage决定这一页总共显示几张卡片                                  *
 *                                                                                *
 * INPUT: runMode -- 运行模式                                                     *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::showCards(int runMode){
	if(runMode == TESTMODE){
		for(int i=0;i<cardsThisPage;i++){
			cardListLayout->addWidget(cards[thisPageBegin + i]);
			cards[thisPageBegin + i]->setVisible(true);
		}
	}else if(runMode == EDITMODE){
		for(int i=0;i<cardsThisPage;i++){
			cardListLayout->addWidget(editableCards[thisPageBegin + i]);
			editableCards[thisPageBegin + i]->setVisible(true);
		}
	}
	qDebug() << "CardList::showCards(int) DONE";
}

/**********************************************************************************
 * CardList::hideCards -- 清除当前显示的卡片                                      *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: cardListLayout里的所有东西都要设为不可见然后移除,否则还是会显示      *
 *           可能和Qt框架的内部机制有关                                           *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::hideCards(){
	while(cardListLayout->count() != 0){
		cardListLayout->itemAt(0)->widget()->setVisible(false);
		cardListLayout->removeItem(cardListLayout->itemAt(0));
	}
	qDebug() << "CardList::hideCards() DONE";
}

/**********************************************************************************
 * CardList::testButton_clicked -- 测试模式运行                                   *
 *                                                                                *
 *   测试模式下显示的是Card对象                                                   *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::testButton_clicked()
{
	//判断数据库是否为空
	if(cardSum == 0){
		qDebug() << "数据库内没有卡片";
		return;
	}

	hideCards();

	//生成用于test的cards
	for(int i=0;i<cardSum;i++){
		cards[i] = new Card(i,heading[i],sentence[i],answer[i],wordPos[i],interference[i],this);
	}

	//判断数据库的卡片够不够显示一页
	if(cardSum < thisPageBegin + CARDSPERPAGE){
		cardsThisPage = cardSum - thisPageBegin;
	}else{
		cardsThisPage = CARDSPERPAGE;
	}
	
	//显示卡片
	showCards(TESTMODE);

	//初始记录数据
	nextPageBegin = thisPageBegin + CARDSPERPAGE;

	adjustSize();

	//锁按键
	runMode = TESTMODE;
	emit lockPlease(TESTMODE);

	qDebug() << "CardList::testButton_clicked() DONE";
}

/**********************************************************************************
 * CardList::editButton_clicked -- 编辑模式运行                                   *
 *                                                                                *
 *   编辑模式下显示的是EditableCard                                               *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::editButton_clicked()
{
	//如果之前构建了card要释放掉
	if(runMode == TESTMODE){
		for(int i=0;i<cardSum;i++)
			cards[i]->deleteLater();
	}

	hideCards();

	//如果是空数据库得初始化第一张卡片
	if(cardSum == 0){
		editableCards[0] = new EditableCard(0,"","","","","");
		cardSum++;
		emit cardSumChanged(cardSum,thisPageBegin);
		activeCard = 0;
		heading.resize(cardSum);
		sentence.resize(cardSum);
		answer.resize(cardSum);
		wordPos.resize(cardSum);
		interference.resize(cardSum);
	}

	//判断数据库的卡片够不够显示一页
	if(cardSum < thisPageBegin + CARDSPERPAGE){
		cardsThisPage = cardSum - thisPageBegin;
	}else{
		cardsThisPage = CARDSPERPAGE;
	}
	
	//显示卡片
	showCards(EDITMODE);

	//初始记录数据
	nextPageBegin = thisPageBegin + CARDSPERPAGE;

	//设置活动卡片
	editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:1px solid gray}");	
	activeCard = thisPageBegin;
	editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:2px solid orange}");	
	editableCards[activeCard]->activateWindow();

	adjustSize();

	//锁按键
	runMode = EDITMODE;
	emit lockPlease(EDITMODE);
}

/**********************************************************************************
 * CardList::sliderValueChanged -- 翻页                                           *
 *                                                                                *
 *   MainWindow通过改变slider部件的值来控制CardList翻页                           *
 *   根据value的值计算出新的thisPageBegin和cardsThisPage,再调用showCards函数      *
 *   实现翻页                                                                     *
 *                                                                                *
 * INPUT: value -- slider部件当前值                                               *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::sliderValueChanged(int value){
	//输入检测
	if(value*CARDSPERPAGE >= cardSum || value < 0){
		qDebug() << "CardList::sliderValueChanged() input ERROR";
		return;
	}

	if(runMode == TESTMODE || runMode == EDITMODE)
		hideCards();

	//翻页数据更新
	thisPageBegin = value*CARDSPERPAGE;
	nextPageBegin = thisPageBegin + CARDSPERPAGE;
	if(value == 0){
		previousPageBegin = 0;
	}else{
		previousPageBegin = thisPageBegin - CARDSPERPAGE;
	}

	if(cardSum < thisPageBegin + CARDSPERPAGE){
		cardsThisPage = cardSum - thisPageBegin;
	}else{
		cardsThisPage = CARDSPERPAGE;
	}

	if(runMode == TESTMODE || runMode == EDITMODE)
		showCards(runMode);

	//更新活动卡片
	if(runMode == EDITMODE){
		editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:1px solid gray}");	
		activeCard = thisPageBegin;
		editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:2px solid orange}");	
	}
	
	qDebug() << "CardList::sliderValueChanged(int) DONE";
}

/**********************************************************************************
 * CardList::insertButton_clicked -- 插入一张新的卡片                             *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: 应该在EDITMODE模式下被触发                                           *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::insertButton_clicked()
{
	qDebug() << "Insert!";

	if(cardSum == MAXCARD){
		qDebug()<<"reached MAXCARD";
		return;
	}

	hideCards();

	//重新排列editableCards[]
	for(int i=cardSum;i>activeCard+1;i--){
		editableCards[i] = editableCards[i-1];
		editableCards[i]->setId(i);
	}

	//初始化新卡
	editableCards[activeCard+1] = new EditableCard(activeCard+1,"","","","","",this);
	connect(editableCards[activeCard+1],SIGNAL(cardPressed(int)),this,SLOT(cardPressed(int)));

	//更新数据
	cardSum++;
	heading.resize(cardSum);
	sentence.resize(cardSum);
	answer.resize(cardSum);
	wordPos.resize(cardSum);
	interference.resize(cardSum);

	//判断新增的卡片是不是在下一页上
	if(activeCard+1 == thisPageBegin+CARDSPERPAGE){
		previousPageBegin = thisPageBegin;
		thisPageBegin = nextPageBegin;
		nextPageBegin = thisPageBegin + CARDSPERPAGE;
		if(cardSum < thisPageBegin + CARDSPERPAGE){
			cardsThisPage = cardSum - thisPageBegin;
		}else{
			cardsThisPage = CARDSPERPAGE;
		}
	}else if(cardsThisPage < CARDSPERPAGE){
		cardsThisPage++;
	}

	showCards(EDITMODE);

	editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:1px solid gray}");	
	activeCard++;
	editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:2px solid orange}");	
	//if(activeCard)
	emit lockPlease(EDITMODE);
	emit cardSumChanged(cardSum,thisPageBegin);
}

/**********************************************************************************
 * CardList::deleteButton_clicked -- 删除一张旧卡                                 *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: 应该在EDITMODE模式下被触发                                           *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::deleteButton_clicked()
{
	qDebug() << "Delete!";

	//只剩一张卡片的时候不能删
	if(cardSum == 1){
		return;
	}

	hideCards();	

	//将activeCard删掉
	editableCards[activeCard]->deleteLater();


	//重新排列editableCards[]
	for(int i=activeCard;i<cardSum-1;i++){
		editableCards[i] = editableCards[i+1];
		editableCards[i]->setId(i);
	}
	editableCards[cardSum-1] = nullptr;
	
	//更新数据
	cardSum--;
	heading.resize(cardSum);
	sentence.resize(cardSum);
	answer.resize(cardSum);
	wordPos.resize(cardSum);
	interference.resize(cardSum);

	if(editableCards[activeCard])
		editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:2px solid orange}");	
	else{
		activeCard = cardSum-1;
		editableCards[activeCard]->setStyleSheet(".EditableCard{background:transparent;border:2px solid orange}");	
	}

	//重新布局页面
	//判断数据库的卡片够不够显示一页,以及要不要换到前一页去
	if(cardSum <= thisPageBegin){
		thisPageBegin -= CARDSPERPAGE;
		nextPageBegin -= CARDSPERPAGE;
		previousPageBegin -= CARDSPERPAGE;
		cardsThisPage = CARDSPERPAGE;
	}else if(cardSum < thisPageBegin + CARDSPERPAGE){
		cardsThisPage = cardSum - thisPageBegin;
	}else{
		cardsThisPage = CARDSPERPAGE;
	}
	
	showCards(EDITMODE);

	//初始记录数据
	nextPageBegin = thisPageBegin + CARDSPERPAGE;

	emit lockPlease(EDITMODE);
	emit cardSumChanged(cardSum,thisPageBegin);
}

/**********************************************************************************
 * CardList::saveButton_clicked -- 保存卡片集                                     *
 *                                                                                *
 *   将当前卡片集的数据写进数据库                                                 *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::saveButton_clicked()
{
	qDebug() << "Save!";
	QSqlDatabase db;
	if(QSqlDatabase::contains("qt_sql_default_connection"))	
		db = QSqlDatabase::database("qt_sql_default_connection");
	else
 		db = QSqlDatabase::addDatabase("QSQLITE");
	db.setDatabaseName("../user/" + dbNameRemain + ".db");
	
	if(!db.open())
		qDebug() << db.lastError().text();

	qDebug() << db.connectionName();

	//将更改的内容写入数据库
	QSqlQuery query;
	QString sql;
	sql = QString("delete from cardlist");
	query.exec(sql);
	query.next();
	db.transaction();
	for(int i=0;i<cardSum;i++){
		heading[i] = editableCards[i]->getHeading();
		sentence[i] = editableCards[i]->getSentence();
		answer[i] = editableCards[i]->getAnswer();
		wordPos[i] = editableCards[i]->getWordPos();
		interference[i] = editableCards[i]->getInterference();
		sql = QString("insert into cardlist(id,heading,sentence,answer,wordPos,interference)values(%2,'%3','%4','%5','%6','%7')").arg(i).arg(sqlMaker(heading[i])).arg(sqlMaker(sentence[i])).arg(sqlMaker(answer[i])).arg(sqlMaker(wordPos[i])).arg(sqlMaker(interference[i]));
		qDebug() << sql;
		query.exec(sql);
		}
	if(!db.commit()){
		qDebug() << db.lastError();
	}else
		emit lockPlease(SAVEMODE);
}

/**********************************************************************************
 * CardList::sqlMaker -- 转化成SQLite可以处理的语句                               *
 *                                                                                *
 *   想要SQLite识别"'"符号的话得写成"''"                                          *
 *                                                                                *
 * INPUT: str -- 原句                                                             *
 *                                                                                *
 * OUTPUT: 处理过后的语句                                                         *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

QString CardList::sqlMaker(QString str)
{
	if(int i = str.indexOf("'"))
		str.insert(i,QString("'"));
	return str;
}

/**********************************************************************************
 * CardList::cardPressed -- 点击EditableCard对象触发的事件                        *
 *                                                                                *
 *   点击EditableCard对象会将其标记为"正在处理的卡片",即activeCard                *
 *   在此基础上插入操作会在activeCard的后面插入一张新卡片                         *
 *   删除操作会把activeCard删除                                                   *
 *                                                                                *
 * INPUT: cardId -- 选中的EditableCard的号码                                      *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

void CardList::cardPressed(int cardId)
{
	activeCard = cardId;
	for(int i=thisPageBegin;i<thisPageBegin+cardsThisPage;i++){
		if(editableCards[i]->getId() != activeCard)
			editableCards[i]->setStyleSheet(QString(".EditableCard{background:transparent;border:1px solid gray}"));
		else
			editableCards[i]->setStyleSheet(QString(".EditableCard{background:transparent;border:2px solid orange}"));
			
	}
}

/**********************************************************************************
 * CardList::getCardSum -- 返回卡片的总数                                         *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: cardSum -- 卡片总数                                                    *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/

int CardList::getCardSum() const{
	return cardSum;
}


